/*
 * Copyright 2014-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
<template>
  <el-dialog v-dialogDrag :title="$t('contracts.transactionReceipt')" :visible.sync="editorDialog" width="650px" top="10vh" @close="modelClose">
    <div v-if="!transationData">{{ $t('text.noData') }}</div>
    <div v-if="transationData && !transationData.logs" slot :style="{'height':editorHeight + 'px'}" style="overflow-y:auto">
      <json-viewer :value="transationData" :expand-depth="5" copyable />
    </div>
    <div v-if="transationData && transationData.logs" slot :style="{'height':editorHeight + 'px'}" style="overflow-y:auto">
      <div>{</div>
      <div v-for="(val,key) in transationData" :key="key" style="padding-left: 10px;">
        <div v-if="key != &quot;logs&quot;&& key != &quot;output&quot;">
          <template v-if="key=='status'">
            <span class="transation-title">{{ key }}:</span>
            <span :style="{'color': txStatusColor(val)}">{{ val }}</span>
          </template>
          <template v-else>
            <span class="transation-title">{{ key }}:</span>
            <span v-if="typeof(val) == &quot;string&quot;" class="transation-content string-color">"{{ val }}"</span>
            <span v-else-if="val === null" class="transation-content null-color">{{ val }}null</span>
            <span v-else-if="typeof(val) == &quot;object&quot;" class="transation-content">{{ val }}</span>
            <span v-else class="transation-content other-color">{{ val }}</span>
          </template>
        </div>
        <div v-else-if="key == &quot;output&quot;">
          <span class="transation-title">{{ key }}:</span>
          <span v-if="showDecode" class="transation-content string-color">"{{ val }}"</span>
          <div v-if="!showDecode" class="transation-data" style="width: 500px">
            <div class="input-label">
              <span class="label">function</span>
              <span>{{ funcData + "(" + abiType +")" +' ' +outputType }}</span>
            </div>
            <div class="input-label">
              <span class="label">data:</span>
              <el-table v-if="inputData.length" :data="inputData" style="display:inline-block;width:350px">
                <el-table-column prop="name" label="name" align="left" />
                <el-table-column prop="type" label="type" align="left" />
                <el-table-column prop="data" label="data" align="left" :show-overflow-tooltip="true">
                  <template slot-scope="scope">
                    <i class="wbs-icon-baocun font-12 copy-public-key" :title="$t('text.copy')" @click="copyPubilcKey(scope.row.data)" />
                    <span>{{ scope.row.data }}</span>
                  </template>
                </el-table-column>
              </el-table>
            </div>
          </div>
          <div v-show="inputButtonShow" class="item">
            <span class="label" />
            <el-button type="primary" @click="decodeOutput">{{ buttonTitle }}</el-button>
          </div>
        </div>
        <div v-if="key == &quot;logs&quot;">
          <span>{{ key }}:</span>
          <span v-if="!val.length">{{ val }}</span>
          <span v-if="val.length">[
            <div v-for="(item,index) in val" :key="index" style="padding-left: 10px;">
              <div>{</div>
              <div style="padding-left: 10px;">
                <div>
                  <span class="transation-title">removed:</span>
                  <span class="transation-content other-color">{{ item.removed }}</span>
                </div>
                <div>
                  <span class="transation-title">logIndex:</span>
                  <span v-if="typeof(item.logIndex) == &quot;string&quot;" class="transation-content string-color">{{ item.logIndex }}</span>
                  <span v-else-if="item.logIndex === null" class="transation-content null-color">{{ item.logIndex }}null</span>
                  <span v-else class="transation-content">{{ item.logIndex }}</span>
                </div>
                <div>
                  <span class="transation-title">transactionIndex:</span>
                  <span v-if="item.transactionIndex === null" class="transation-content null-color">{{ item.transactionIndex }}null</span>
                  <span v-else class="transation-content">{{ item.transactionIndex }}</span>
                </div>
                <div>
                  <span class="transation-title">transactionHash:</span>
                  <span v-if="typeof(item.transactionHash) == &quot;string&quot;" class="transation-content string-color">{{ item.transactionHash }}</span>
                  <span v-else-if="item.transactionHash === null" class="transation-content null-color">{{ item.transactionHash }}null</span>
                  <span v-else class="transation-content">{{ item.transactionHash }}</span>
                </div>
                <div>
                  <span class="transation-title">blockHash:</span>
                  <span v-if="typeof(item.blockHash) == &quot;string&quot;" class="transation-content string-color">{{ item.blockHash }}</span>
                  <span v-else-if="item.blockHash === null" class="transation-content null-color">{{ item.blockHash }}null</span>
                  <span v-else class="transation-content">{{ item.blockHash }}</span>
                </div>
                <div>
                  <span class="transation-title">blockNumber:</span>
                  <span v-if="item.blockNumber === null" class="transation-content null-color">{{ item.blockNumber }}null</span>
                  <span v-else class="transation-content">{{ item.blockNumber }}</span>
                </div>
                <div>
                  <span class="transation-title">address:</span>
                  <span v-if="typeof(item.address) == &quot;string&quot;" class="transation-content string-color">{{ item.address }}</span>
                  <span v-else-if="item.address === null" class="transation-content null-color">{{ item.address }}null</span>
                  <span v-else class="transation-content">{{ item.address }}</span>
                </div>
                <div v-if="item.eventDataShow && eventSHow">
                  <span class="transation-title">eventName :</span>
                  <span class="transation-content">{{ item.eventName }}</span>
                </div>
                <div>
                  <span class="transation-title">data:</span>
                  <span v-show="!item.eventDataShow && eventSHow" class="transation-content string-color">{{ item.data }}</span>
                  <div v-show="item.eventDataShow && eventSHow" class="transation-data">
                    <el-table class="input-data" :data="item.eventLgData" style="display:inline-block;width:100%;">
                      <el-table-column prop="name" width="150" label="name" align="left" />
                      <el-table-column prop="data" label="data" align="left" :show-overflow-tooltip="true">
                        <template slot-scope="scope">
                          <i class="wbs-icon-baocun font-12 copy-public-key" :title="$t('text.copy')" @click="copyPubilcKey(scope.row.data)" />
                          <span>{{ abc(scope.row.data) }}</span>
                        </template>
                      </el-table-column>
                    </el-table>
                  </div>
                  <div class="item">
                    <span class="label" />
                    <el-button type="primary" @click="decode(item)">{{ eventTitle }}</el-button>
                  </div>
                </div>
                <div>
                  <span class="transation-title">type:</span>
                  <span v-if="typeof(item.type) == &quot;string&quot;" class="transation-content string-color">{{ item.type }}</span>
                  <span v-else-if="item.type === null" class="transation-content null-color">{{ item.type }}null</span>
                  <span v-else class="transation-content">{{ item.type }}</span>
                </div>
                <div>
                  <span class="transation-title">topics:</span>
                  <span v-if="typeof(item.topics) == &quot;string&quot;" class="transation-content string-color">{{ item.topics }}</span>
                  <span v-else-if="item.topics === null" class="transation-content null-color">{{ item.topics }}null</span>
                  <span v-else class="transation-content">{{ item.topics }}</span>
                </div>
                <div>
                  <span class="transation-title">logIndexRaw:</span>
                  <span v-if="typeof(item.logIndexRaw) == &quot;string&quot;" class="transation-content string-color">{{ item.logIndexRaw }}</span>
                  <span v-else-if="item.logIndexRaw === null" class="transation-content null-color">{{ item.logIndexRaw }}null</span>
                  <span v-else class="transation-content">{{ item.logIndexRaw }}</span>
                </div>
              </div>
              <div>}</div>
            </div>
            ]
          </span>
        </div>
      </div>
      <div>}</div>
    </div>
  </el-dialog>
</template>
<script>
import { getFunctionAbi } from '@/api/exercises'
import { debuglog } from 'util'
import { toContractName } from '@/utils/util'
export default {
  name: 'Editor',
  props: ['data', 'show', 'input', 'editorOutput', 'sendConstant'],
  data: function() {
    return {
      editorShow: true,
      aceEditor: null,
      transationData: this.data || null,
      modePath: 'ace/mode/solidity',
      editorDialog: this.show || false,
      eventSHow: false,
      eventTitle: this.$t('transaction.reduction'),
      funcData: '',
      methodId: '',
      abiType: '',
      inputData: [],
      decodeData: '',
      showDecode: true,
      buttonTitle: this.$t('transaction.decode'),
      typesArray: this.input,
      inputButtonShow: true,
      editorHeight: '',
      outputType: null
    }
  },
  mounted: function() {
    this.editorHeight = document.body.offsetHeight * 0.75
    if (this.transationData.output == '0x') {
      this.inputButtonShow = false
    } else {
      this.inputButtonShow = true
    }
    if (this.transationData && this.transationData.logs) {
      this.decodeEvent()
    }
    if (!this.sendConstant) {
      if (this.typesArray && this.transationData.output != '0x') {
        this.decodefun()
      }
    }
    for (const key in this.data) {
      if (this.data.hasOwnProperty(key)) {
        if (key == 'to') {
          const element = this.data[key]
          this.data[key] = `${element} ${toContractName(element)}`
        }
      }
    }
  },
  methods: {
    abc(arr) {
      if (!Array.isArray(arr)) { return arr }
      return '[' + arr.toString() + ']'
      //     if(arr !=Array){return arr}
      //     var str = "[";
      //     arr.forEach(function(item,index,arr){
      //       str += item+',';
      //   })
      //      var a= str.substring(0,(str.length-1));
      //    return a+"]";
      // },
      //  abc(arr){
      //     arr.forEach(function(item,index,arrs){
      //       if(Number(item)){
      //           arrs[index]=Number(item)
      //       }
      //   })
      // //   return arr
      // },
    },
    decodeOutput: function() {
      if (this.showDecode) {
        this.showDecode = false
        this.buttonTitle = this.$t('transaction.reduction')
      } else {
        this.showDecode = true
        this.buttonTitle = this.$t('transaction.decode')
      }
    },
    decodefun: function() {
      const web3 = new Web3(Web3.givenProvider)
      if (this.typesArray) {
        this.typesArray.inputs.forEach((val, index) => {
          if (val && index < this.typesArray.inputs.length - 1) {
            this.abiType = this.abiType + val.type + ' ' + val.name + ','
          } else if (val && index == this.typesArray.inputs.length - 1) {
            this.abiType = this.abiType + val.type + ' ' + val.name
          }
        })
        this.funcData = this.typesArray.name
        if (this.editorOutput.length) {
          this.decodeData = web3.eth.abi.decodeParameters(this.editorOutput, this.transationData.output)
          if (JSON.stringify(this.decodeData) != '{}') {
            for (const key in this.decodeData) {
              for (let index = 0; index < this.editorOutput.length; index++) {
                this.inputData[index] = {}
                this.inputData[index].name = this.editorOutput[index].name
                this.inputData[index].type = this.editorOutput[index].type
                this.inputData[index].data = this.decodeData[index]
              }
            }
          }
          const outputType = []
          this.editorOutput.forEach((val, index) => {
            if (val && val.type && val.name) {
              outputType[index] = val.type + ' ' + val.name
            } else if (val && val.name) {
              outputType[index] = val.name
            } else if (val && val.type) {
              outputType[index] = val.type
            } else if (val) {
              outputType[index] = val
            }
          })
          this.outputType = `returns(${outputType.join(', ')})`
        } else {
          this.outputType = ''
        }
        this.showDecode = false
        this.buttonTitle = this.$t('transaction.reduction')
      }
    },
    decodeEvent: function() {
      for (let i = 0; i < this.transationData.logs.length; i++) {
        const data = {
          groupId: 1,
          data: this.transationData.logs[i].topics[0]
        }
        getFunctionAbi(data).then(res => {
          if (res.code === 0 && res.data) {
            this.transationData.logs[i] = this.decodeLogs(res.data, this.transationData.logs[i])
            setTimeout(() => {
              this.eventSHow = true
            }, 200)
          } else if (res.data.code !== 0) {
            this.$messageOnce({
              type: 'error',
              message: this.$chooseLang(res.code)
            })
          }
        }).catch(err => {
          console.log('getFunctionAbi')
          this.$messageOnce({
            type: 'error',
            message: this.$t('text.systemError')
          })
        })
      }
    },
    decodeLogs: function(eventData, data) {
      const web3 = new Web3(Web3.givenProvider)
      const abi = ''
      eventData.abiInfo = JSON.parse(eventData.abiInfo)
      const list = data
      list.eventTitle = this.$t('transaction.reduction')
      list.eventDataShow = true
      list.eventButtonShow = true
      list.eventName = eventData.abiInfo.name + '('
      for (let i = 0; i < eventData.abiInfo.inputs.length; i++) {
        if (i == eventData.abiInfo.inputs.length - 1) {
          if (eventData.abiInfo.inputs[i]['indexed']) {
            list.eventName = list.eventName + eventData.abiInfo.inputs[i].type + ' ' + 'indexed' + ' ' + eventData.abiInfo.inputs[i].name
          } else {
            list.eventName = list.eventName + eventData.abiInfo.inputs[i].type + ' ' + eventData.abiInfo.inputs[i].name
          }
        } else {
          if (eventData.abiInfo.inputs[i]['indexed']) {
            list.eventName = list.eventName + eventData.abiInfo.inputs[i].type + ' ' + 'indexed' + ' ' + eventData.abiInfo.inputs[i].name + ','
          } else {
            list.eventName = list.eventName + eventData.abiInfo.inputs[i].type + ' ' + eventData.abiInfo.inputs[i].name + ','
          }
        }
      }
      list.eventName = list.eventName + ')'
      const eventResult = web3.eth.abi.decodeLog(eventData.abiInfo.inputs, list.data, list.topics.slice(1))
      list.outData = {}
      list.eventLgData = []
      for (const key in eventResult) {
        if (+key || +key == 0) {
          list.outData[key] = eventResult[key]
        }
      }
      if (eventData.abiInfo.inputs.length && JSON.stringify(list.outData) != '{}') {
        for (const key in list.outData) {
          eventData.abiInfo.inputs.forEach((items, index) => {
            if (index == key) {
              list.eventLgData[index] = {}
              list.eventLgData[index].name = items.name
              list.eventLgData[index].data = list.outData[key]
            }
          })
        }
      }
      return list
    },
    copyPubilcKey: function(val) {
      if (!val) {
        this.$messageOnce({
          type: 'fail',
          showClose: true,
          message: this.$t('text.copyErrorMsg'),
          duration: 2000
        })
      } else {
        this.$copyText(val).then(e => {
          this.$messageOnce({
            type: 'success',
            showClose: true,
            message: this.$t('text.copySuccessMsg'),
            duration: 2000
          })
        })
      }
    },
    modelClose: function() {
      this.$emit('close')
    },
    decode: function(val) {
      if (val.eventDataShow) {
        this.$set(val, 'eventDataShow', false)
        this.eventTitle = this.$t('transaction.decode')
      } else {
        this.$set(val, 'eventDataShow', true)
        this.eventTitle = this.$t('transaction.reduction')
      }
    },
    txStatusColor(val) {
      if (val == '0x0') {
        return '#67C23A'
      } else {
        return '#F56C6C'
      }
    }
  }
}
</script>
<style>
.transation-content {
    word-wrap: break-word;
    word-break: break-all;
}
.transation-title {
    color: #333;
}
.string-color {
    color: #42b983;
}
.null-color {
    color: #e08331;
}
.other-color {
    color: #fc1e70;
}
.input-data {
    display: inline-block;
    width: 100%;
    padding: 10px;
    max-height: 200px;
    overflow: auto;
    word-break: break-all;
    word-wrap: break-word;
    box-sizing: border-box;
}
.transation-data {
    display: inline-block;
    width: 400px;
    vertical-align: top;
}
.label {
    vertical-align: top;
    padding-right: 5px;
}
</style>

